package com.mdn.poi.util;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class XlsxHelper {

	private static final String DATE_FORMAT = "dd/MM/yyyy HH:mm";
	private static XSSFCellStyle dateStyle;
	
	public static XSSFWorkbook getBook(String sheetTitle, String[]headers, String[] fields, List<?> data){
		XSSFWorkbook workbook = new XSSFWorkbook();		

		// Propiedades del documento -- NO FUNCIONA BIEN
//		workbook.getProperties().getExtendedProperties().getUnderlyingProperties().setCompany("BBVA");
//		workbook.getProperties().getCustomProperties().addProperty("Author", "Autor BBVA");
//		workbook.getProperties().getCustomProperties().addProperty("Created", new Date().toString());

		// Para crear el formato de fecha
		createDateStyle(workbook);
		
		// Crea la hoja con el título que queramos
		XSSFSheet sheet = workbook.createSheet(sheetTitle);
		// La primera fila, la de los títulos, no se moverá
		sheet.createFreezePane(0, 1); 

		// Metemos los títulos
		int rownum = 0;
		Row row = sheet.createRow(rownum++);
		addTitles(row, headers);
		
		// Y ahora la información de los informes
		for(Object obj : data){
			row = sheet.createRow(rownum++);
			addData(row, obj, fields);			
		}		
		return workbook;
	}

	/**
	 * Crea el estilo para los campos de fecha
	 * @param workbook
	 */
	private static void createDateStyle(XSSFWorkbook workbook){
		dateStyle = workbook.createCellStyle();
		short dateFormat = workbook.createDataFormat().getFormat(DATE_FORMAT);
		dateStyle.setDataFormat(dateFormat);
	}
	
	/**
	 * Añade la fila con los títulos de las columnas
	 * @param row
	 * @param titles
	 */
	private static void addTitles(Row row, String[]titles){
		int cellnum = 0;
		for(String title : titles){
			Cell cell = row.createCell(cellnum++);
			cell.setCellValue(title);			
		}
	}

	/**
	 * Añade una fila con los valores del objecto pasado como parámetro
	 * @param row
	 * @param obj
	 * @param fields
	 */
	private static void addData(Row row, Object obj, String[] fields){
		int cellnum = 0;
		for(String fieldName : fields){
			Cell cell = row.createCell(cellnum++);
			Object toAdd = executeGetMethod(obj, fieldName);
			if(toAdd != null){
				if(toAdd instanceof String){
					cell.setCellValue((String)toAdd);
				}else if(toAdd instanceof Date){
					cell.setCellStyle(dateStyle);
					cell.setCellValue((Date)toAdd);
				}else if(toAdd instanceof Boolean){
					cell.setCellValue((Boolean)toAdd);
				}else if(toAdd instanceof Double){
					cell.setCellValue((Double)toAdd);
				}else if(toAdd instanceof Long){
					cell.setCellValue((Long)toAdd);
				}else{
					cell.setCellValue(toAdd.toString());
				}
			}else{
				cell.setCellValue("");
			}
		}
	}
	
	private static Object executeGetMethod(Object classInstance, String fieldName) {
		try {
			Field field = classInstance.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			return field.get(classInstance);
		} catch (Exception e) {
			return null;
		}
	}	
}
